package utils;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.*;
import java.util.regex.Pattern;

public class RegexUtil {
    // 设置正则表达式匹配的超时时间（毫秒）
    private static final int REGEX_TIMEOUT = 3000;
    
    // 正则表达式缓存的最大大小
    private static final int MAX_PATTERN_CACHE_SIZE = 100;

    // 创建一个单线程的执行器服务用于正则表达式匹配
    private static final ExecutorService regexExecutor = Executors.newSingleThreadExecutor();
    
    // 正则表达式缓存，使用LRU策略
    private static final Map<String, Pattern> patternCache = new LinkedHashMap<>(16, 0.75f, true) {
        protected boolean removeEldestEntry(Map.Entry<String, Pattern> eldest) {
            return size() > MAX_PATTERN_CACHE_SIZE;
        }
    };

    /**
     * 获取缓存的正则表达式Pattern对象
     *
     * @param patternStr 正则表达式字符串
     * @return 编译后的Pattern对象
     */
    private static Pattern getCachedPattern(String patternStr) {
        synchronized (patternCache) {
            return patternCache.computeIfAbsent(patternStr, Pattern::compile);
        }
    }

    /**
     * 安全的正则表达式匹配，包含超时机制和缓存优化
     *
     * @param patternStr 正则表达式字符串
     * @param input 输入字符串
     * @return 是否匹配
     * @throws TimeoutException 当匹配超时时抛出
     */
    public static boolean safeRegexMatch(String patternStr, String input) throws TimeoutException {
        Pattern pattern = getCachedPattern(patternStr);
        Callable<Boolean> task = () -> pattern.matcher(input).find();

        Future<Boolean> future = regexExecutor.submit(task);

        try {
            return future.get(REGEX_TIMEOUT, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("Regex matching interrupted", e);
        } catch (ExecutionException e) {
            throw new RuntimeException("Regex matching execution error", e);
        } catch (TimeoutException e) {
            future.cancel(true); // 取消任务
            throw e;
        }
    }

    /**
     * 关闭正则表达式执行器
     */
    public static void shutdownRegexExecutor() {
        regexExecutor.shutdown();
        try {
            if (!regexExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                regexExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            regexExecutor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}
